package components
{
	import flash.display.DisplayObject;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.ui.Keyboard;
	import flash.utils.getQualifiedClassName;
	import flash.utils.getTimer;
	
	import oboe.core.Controller;
	import oboe.core.Oboe;
	
	
	public class Component extends Controller
	{
		private var data:ComponentData;
		public var id:int;

		private static var idCounter:int=0;
		private var finalName:String;
		
		public function Component(displayObject:DisplayObject=null, data:Object=null)
		{
			super(displayObject);
			
			this.finalName = getQualifiedClassName(this).replace(/[^:]*::(.*)/g, "$1");
			
			this.data = this.createData( data );
			
			if( this.data.id > 0 )
			{
				if( this.id > idCounter ) idCounter = this.id;
			}
			else
			{
				this.id = ++idCounter;
			}
			
			this.addAssetCallbackEx( MouseEvent.MOUSE_DOWN, onMouseDown );
			this.addAssetCallbackEx( MouseEvent.MOUSE_DOWN, onMouseUp );
			
			if( "x" in this.data && "y" in this.data ) this.setPosition( this.data["x"], this.data["y"] );
		}
		
		protected function createData( data:Object ):ComponentData
		{
			throw "MUST OVERRIDE";
		}
		
		public function getData():ComponentData
		{
			return this.data;
		}
		
		public function getUpdatedData():ComponentData
		{
			this.data.readFrom( this );
			return this.data;
		}
		
		private var dragged:Boolean;
		private static var selected:Component = null;
		private var timeSinceLastUp:Number = 0;
		private function onMouseUp( e:MouseEvent ):void
		{
			if( dragged ) return;
			
			var clickType:String = "";
			
			var time:Number = getTimer();
			var dbl:Boolean = time - this.timeSinceLastUp < 300; 
			if( dbl ) clickType += "Dbl";
			this.timeSinceLastUp = time;
			
			if( e.altKey )   clickType += "Alt";
			if( e.shiftKey ) clickType += "Shift";
			if( e.ctrlKey )  clickType += "Ctrl";

			if( clickType != "" )
			{
				clickType = clickType.substr(0,1).toLowerCase() + clickType.substr(1);
				
				if( selected && !dbl)
				{
					this.signalUp( clickType + "Click" + this.finalName + "WithSelection", this, selected);
				}
				else
				{
					this.signalUp( clickType + "Click" + this.finalName, this);
				}
			}
			else
			{
				this.setSelected( true );
			}
		}
		
		[slot] public function setSelected( state:Boolean ):void
		{
			if( 
				(selected == this && state) ||
				selected != this && !state
				) return;
			
			if( state && selected && selected != this ) selected.setSelected( false );
			
			var asset:DisplayObject = this.getDisplayObject();
			if( state )
			{
				Oboe.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown );
			}
			else
			{
				Oboe.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);			
			}
			
			selected = state?this:null;
		}
		
		[slot] public function destruct():void
		{
			this.selfDestruct();
		}
		
		private function onMouseDown( e:MouseEvent ):void
		{
			this.dragged = false;
			var asset:DisplayObject = this.getDisplayObject();
			asset.parent.addEventListener( MouseEvent.MOUSE_MOVE, onDrag );
		}
		
		private function cancelDrag():void
		{
			var asset:DisplayObject = this.getDisplayObject();
			asset.parent.removeEventListener(MouseEvent.MOUSE_MOVE, onDrag );			
		}
		
		private function onKeyDown( e:KeyboardEvent ):void
		{
			if( e.target is TextField && TextField(e.target).type == TextFieldType.INPUT ) return;
			
			if( e.keyCode == Keyboard.BACKSPACE || e.keyCode == Keyboard.DELETE )
			{
				this.cancelDrag();
				this.selfDestruct();
			}
		}
		
		private function onDrag(e:MouseEvent):void{
			if(!e.buttonDown)
			{
				this.cancelDrag();
				return;
			}
			this.dragged = true;
			this.setPosition( e.stageX, e.stageY );
		}
		
		protected function setPosition( x:Number, y:Number ):void
		{
			var asset:DisplayObject = this.getDisplayObject();
			asset.x = x;
			asset.y = y;
		}
	}
}